package com.hczt.fire.server.config.sercurity.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hczt.fire.server.config.sercurity.annotation.ContentSecurity;
import com.hczt.fire.server.config.sercurity.constants.ContentSecurityConstants;
import com.hczt.fire.server.config.sercurity.util.DES3Util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Iterator;

/**
 * 精诚所至，金石为开。
 * 石の上にも三年;陽気の発する所金石亦透る。
 * Faith moves mountains.
 *
 * @author marvin.ma
 * @create 2017-11-29 22:34
 * @desc 安全认证拦截器
 **/
public class ContentSecurityInterceptor implements HandlerInterceptor {

    private static Logger logger = LoggerFactory.getLogger(ContentSecurityInterceptor.class);

    /**
     *  请求之前处理加密内容
     * @Auther: marvin.mma
     * @Date: 2017/11/29 22:36
     * @return   
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean isPass = true;

        /**
         * 获取请求映射方法对象
         */
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        /**
         * 获取访问方法实例对象
         */
        Method method = handlerMethod.getMethod();

        /**
         * 检查是否存在内容安全验证注解
         */
        ContentSecurity security = method.getAnnotation(ContentSecurity.class);

        /**
         *  存在注解做出不同方式认证处理
         */
        if (security != null) {
            switch (security.away()) {
                //DES方式加密内容处理
                case DES:
                    isPass = checkDES(request, response);
                    break;
            }
        }
        return isPass ;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    /**
     * 检查DES方式内容
     * @param request
     * @param response
     * @return
     */
    boolean checkDES(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //获取desString加密内容
        String des = null;
        //get方法，请求参数从url后面获取
        //if(RequestMethod.GET.toString().equalsIgnoreCase(request.getMethod())) {
        //    des = request.getParameter(ContentSecurityConstants.DES_PARAMETER_NAME);
        //} else if (RequestMethod.POST.toString().equalsIgnoreCase(request.getMethod())
        //        || RequestMethod.DELETE.toString().equalsIgnoreCase(request.getMethod())
        //        || RequestMethod.PUT.toString().equalsIgnoreCase(request.getMethod())) {
        //    //post方法， 请求参数从post body获取，结构是json的。
        //    MyRequestWrapper myRequestWrapper = new MyRequestWrapper(request);
        //    String body = myRequestWrapper.getBody();
        //    JSONObject jsonObject = (JSONObject) JSONObject.parse(body);
        //    des = (String) jsonObject.get(ContentSecurityConstants.DES_PARAMETER_NAME);
        //}
        des = request.getParameter(ContentSecurityConstants.DES_PARAMETER_NAME);
        logger.info("请求加密参数内容：{}", des);
        /**
         * 加密串不存在
         */
        if (des == null || des.length() == 0) {

            //ApiResult apiResult = ApiResultGenerator
            //        .error()
            //        .msg("The DES Content Security Away Request，Parameter Required is "+ContentSecurityConstants.DES_PARAMETER_NAME)
            //        .build();
            //response.getWriter().print(JSON.toJSONString(apiResult));
            JSONObject json = new JSONObject();
            json.put("msg", "The DES Content Security Away Request , Parameter Required is " + ContentSecurityConstants.DES_PARAMETER_NAME);
            response.getWriter().print(JSON.toJSONString(json));
            return false;
        }

        /**
         * 存在加密串
         * 解密DES参数列表并重新添加到request内
         */
        try {
            des = DES3Util.decrypt(des, DES3Util.DESKEY, ContentSecurityConstants.CONTENT_CHARSET);

            if (!StringUtils.isEmpty(des)) {

                //if (RequestMethod.GET.toString().equalsIgnoreCase(request.getMethod())) {
                //    String[] getParams = des.split("&");
                //    Map<String, Object> map = new HashMap<>();
                //    for (int i=0; i<getParams.length;i++) {
                //        String[] p = getParams[i].split("=");
                //        if (p.length == 2) {
                //            map.put(p[0], p[1]);
                //        }
                //    }
                //    des = JSONUtil.toJsonStr(map);
                //}

                JSONObject params = JSON.parseObject(des);

                logger.info("解密请求后获得参数列表  >>> {}", des);
                Iterator it = params.keySet().iterator();
                while (it.hasNext()) {
                    /**
                     * 获取请求参数名称
                     */
                    String parameterName = it.next().toString();
                    /**
                     * 参数名称不为空时将值设置到request对象内
                     * key=>value
                     */
                    if (!StringUtils.isEmpty(parameterName)) {
                        request.setAttribute(ContentSecurityConstants.ATTRIBUTE_PREFIX + parameterName, params.get(parameterName));
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            //ApiResult apiResult = ApiResultGenerator
            //        .error()
            //        .msg("The DES Content Security Error."+ContentSecurityConstants.DES_PARAMETER_NAME)
            //        .build();
            //response.getWriter().print(JSON.toJSONString(apiResult));

            JSONObject json = new JSONObject();
            json.put("msg","The DES Content Security Error." + ContentSecurityConstants.DES_PARAMETER_NAME);
            response.getWriter().print(JSON.toJSONString(json));
            return false;
        }
        return true;
    }
}
